package edu.unc.comp410.colemangeer.model;

import java.util.Set;

import org.apache.log4j.Logger;

import edu.unc.comp410.colemangeer.model.object.MutableObject;

/**
 * Shopping Cart object is associated with a Customer's shopping session
 * Interface = constructor, gettrs, settrs, service methods,
 * constraints as needed
 * 
 */

public class ShoppingCart extends MutableObject{ //implements IConstraint?

	private static Logger log = Logger.getLogger(ShoppingCart.class);
	
	/**
	 * The customer that this cart is associated with
	 */
	private Customer customer;
	private OrderItems cartItems;  // the public interface for adding and 
								   // deleting items will be implemented
								  // by calls to cartItems
	
	private ShippingInfo shippingInfo;
	private PaymentAuthorization paymentAuthorization;
	
	/**
	 * The order generated from this cart
	 */
	private Order order = null;

	/**
	 * Public constructors
	 */
	private ShoppingCart(){
		log.debug("constructor called with no customer");
		cartItems = new OrderItems();
	}

	public ShoppingCart(Customer c){
		log.warn("Shopping cart created for customer: " + c.toString());
		cartItems = new OrderItems();
	}
	
	/**
	 * Public interface methods
	 */
	
	//Item-related methods
	public void clearItems(){
	}
	
	//add item - quantity 1 by default
	public void addItem(CatalogItem item){
		addItem(item,1);
	}
	
	public void addItem(CatalogItem item, int quantity){
		LineItem lineItem = new LineItem(item,Integer.valueOf(quantity));
		cartItems.addLineItem(lineItem);
		log.warn("added " + quantity  + " of " + item.toString() + " to cart.");
	}

	//remove all quantity of an item
	public void deleteItem(CatalogItem item){
		log.warn("cart deletes catalog item " + item.toString());
		cartItems.removeLineItem(item);
	}
	
	
	//maybe get rid of this - not in use cases
	public void changeItemQuantity(CatalogItem item, int quantity){
		log.warn("cart sets catalog item quantity to " + quantity + " for " + item.toString());
		cartItems.alterItemQuantity(item, quantity);
	}

	
	public String listCartContents(){
		Set<LineItem> lineItems = cartItems.getAllItems();
		StringBuilder sb = new StringBuilder("Items in cart:\n");
		for (LineItem item: lineItems){
			sb.append(item.toString()).append("\n");
		}
		return sb.toString();
	}
	
	
	public double getBasePrice(){
		return cartItems.getBasePrice();
	}
	
	public Object getSalePrice(){
		if (shippingInfo != null){
		return cartItems.getSalePrice(shippingInfo);
		}
		else{
			log.error("Can't get sale price without shipping info");
			return null;
		}
	}
	/**
	 * Create an order from the shopping cart contents
	 */
	public void initiateOrder(){
		log.warn("Cart is initiating order");
		log.warn(listCartContents());
	}
	
	public boolean hasShippingInfo(){
		boolean result =  (shippingInfo != null);
		String msg = result? "Cart has shipping info": "Cart needs shipping info";
		log.warn(msg);
		return result;
	}
	
	
	public boolean hasPaymentAuth(){
		boolean result =  (paymentAuthorization != null);
		String msg = result? "Cart has payment auth": "Cart needs payment auth";
		log.warn(msg);
		return result;
	}
	
	public Order completeCheckout() throws IllegalStateException{

		 makeLegalOrder();
		 return order;

	}
	
	public void makeLegalOrder(){
		log.warn("makeLegalOrder() called");
		if(validate()){
			//TODO: price
			order = new Order(null, customer, cartItems,
					paymentAuthorization, shippingInfo, (Double)getSalePrice());
			log.warn("Shopping cart has made Order!");
			return;
		}
		else{
			log.warn("Shopping cart was asked to make order, but can't");
			throw new IllegalStateException();
		}
	}
	


	/**
	 * Getters and Setters
	 */
	
	public Customer getCustomer() {
		return customer;
	}
	
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public ShippingInfo getShippingInfo() {
		return shippingInfo;
	}

	public void setShippingInfo(ShippingInfo shippingInfo) {
		this.shippingInfo = shippingInfo;
	}

	public PaymentAuthorization getPaymentAuthorization() {
		return paymentAuthorization;
	}

	public void setPaymentAuthorization(PaymentAuthorization paymentAuthorization) {
		this.paymentAuthorization = paymentAuthorization;
	}

	/**
	 * Inherited methods
	 */
	//TODO: implement inherited method
	@Override
	public Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}

	//TODO: implement inherited method
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		return false;
	}

	//TODO: implement inherited method
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return 0;
	}

	//TODO: implement inherited method
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean validate(){
		return hasPaymentAuth() && hasShippingInfo(); // && cartItems.count > 0
	}
}
